package com.coocaa.app.lib.cleaner.mgr.impl;

import com.coocaa.app.lib.cleaner.deleter.utils.FileUtils;
import com.coocaa.app.lib.cleaner.mgr.DataHolder;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by lu on 17-4-11.
 */

public class DataHolderImpl implements DataHolder {
    private final static long SIZE_GATE = 12288;
    public static final DataHolderImpl instance = new DataHolderImpl();

    private DataHolderListener listener;

    private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();

    private final ApkRubbish apkRubbish = new ApkRubbish();
    private final PackageCache packageCache = new PackageCache();
    private final PackageData packageData = new PackageData();
    private final OtherData otherData = new OtherData();

    @Override
    public void reset(DataHolderListener listener) {
        this.listener = listener;
        synchronized (apkRubbish) {
            apkRubbish.reset();
        }
        synchronized (packageCache) {
            packageCache.reset();
        }
        synchronized (packageData) {
            packageData.reset();
        }
        synchronized (otherData) {
            otherData.reset();
        }
    }

    @Override
    public void appendAPK(final String apk) {
        synchronized (apkRubbish) {
            long size = new File(apk).length();
            if (size > 0) {
                apkRubbish.apks.put(apk, size);
                apkRubbish.size += size;
                final ApkRubbish r = apkRubbish.clone();
                EXECUTOR.execute(new Runnable() {
                    @Override
                    public void run() {
                        if (listener != null)
                            listener.onApkRubbishUpdate(r, apk);
                    }
                });
            }
        }
    }

    @Override
    public void appendPackageCache(final SinglePackageCache cache) {
        synchronized (packageCache) {
            packageCache.caches.add(cache);
            packageCache.size += cache.size;
            final PackageCache r = packageCache.clone();
            EXECUTOR.execute(new Runnable() {
                @Override
                public void run() {
                    if (listener != null)
                        listener.onPackageCacheUpdate(r, cache.packageName);
                }
            });
        }
    }

    @Override
    public void appendPackageData(final SinglePackageData data) {
        synchronized (packageData) {
            packageData.datas.add(data);
            packageData.size += data.size;
            final PackageData r = packageData.clone();
            EXECUTOR.execute(new Runnable() {
                @Override
                public void run() {
                    if (listener != null)
                        listener.onPackageDataUpdate(r, data.packageName);
                }
            });
        }
    }

    @Override
    public void appendOtherData(final String file) {
        synchronized (otherData) {
            long size = FileUtils.getFileSize(file);
            if (size > SIZE_GATE) {
                otherData.datas.put(file, size);
                otherData.size += size;
                final OtherData r = otherData.clone();
                EXECUTOR.execute(new Runnable() {
                    @Override
                    public void run() {
                        if (listener != null)
                            listener.onOtherDataUpdate(r, file);
                    }
                });
            }
        }
    }

    @Override
    public void removeAPK(String apk) {
        synchronized (apkRubbish) {
            Long size = apkRubbish.apks.get(apk);
            if (size != null) {
                apkRubbish.size -= size;
                apkRubbish.apks.remove(apk);
            }
        }
    }

    @Override
    public void removePackageCache(SinglePackageCache cache) {
        synchronized (packageCache) {
            if (packageCache.contains(cache)) {
                packageCache.size -= cache.size;
                packageCache.remove(cache);
            }
        }
    }

    @Override
    public void removePackageData(SinglePackageData data) {
        synchronized (packageData) {
            if (packageData.contains(data)) {
                packageData.size -= data.size;
                packageData.remove(data);
            }
        }
    }

    @Override
    public void removeOtherData(String file) {
        synchronized (otherData) {
            Long size = otherData.datas.get(file);
            if (size != null) {
                otherData.size -= size;
                otherData.datas.remove(file);
            }
        }
    }

    @Override
    public ApkRubbish getApkRubbish() {
        synchronized (apkRubbish) {
            return apkRubbish.clone();
        }
    }

    @Override
    public PackageCache getPackageCache() {
        synchronized (packageCache) {
            return packageCache.clone();
        }
    }

    @Override
    public PackageData getPackageData() {
        synchronized (packageData) {
            return packageData.clone();
        }
    }

    @Override
    public OtherData getOtherData() {
        synchronized (otherData) {
            return otherData.clone();
        }
    }
}
